# -*- coding: utf-8 -*-
import codecs
import json
import logging
import os
import pkg_resources
from os.path import abspath
try:
    from os import scandir
except ImportError:
    from scandir import scandir

import click
from docx import Document
from docx.shared import Pt
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT

# 添加 PDF 支持
try:
    from reportlab.lib.pagesizes import A4, letter
    from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
    from reportlab.lib.units import inch
    from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
    from reportlab.pdfbase import pdfmetrics
    from reportlab.pdfbase.ttfonts import TTFont
    from reportlab.lib.enums import TA_LEFT
    PDF_AVAILABLE = True
except ImportError:
    PDF_AVAILABLE = False
    print("警告: reportlab 库未安装，PDF 输出功能不可用。请运行 'pip install reportlab' 安装。")

# 在文件开头添加导入
try:
    from .markdown_to_pdf import MarkdownToPDFWriter, markdown_to_pdf
    MARKDOWN_PDF_AVAILABLE = True
except ImportError:
    MARKDOWN_PDF_AVAILABLE = False
    print("警告: markdown转PDF功能不可用，请安装相关依赖。")


logger = logging.getLogger(__name__)

# 配置文件路径
CONFIG_FILE = os.path.join(os.path.dirname(__file__), '..', 'config.json')

# 加载配置
def load_config():
    """加载配置文件"""
    try:
        with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        logger.warning(f"配置文件 {CONFIG_FILE} 未找到，使用默认配置")
        return get_default_config()
    except json.JSONDecodeError as e:
        logger.error(f"配置文件格式错误: {e}，使用默认配置")
        return get_default_config()

def get_default_config():
    """获取默认配置"""
    return {
        "max_lines": 3200,
        "first_page_file_path": "C:/code/cef-project/third_party/cef/cef_binary_106.0.26+ge105400+chromium-106.0.5249.91_windows32/tests/doudian_tool/cefclient_win.cc",
        "default_indirs": ["."],
        "default_exts": ["py", "cc", "cpp", "h", "js"],
        "default_comment_chars": ["#", "//"],
        "default_title": "翻天印易开店网店管理软件V1.0",
        "default_font_settings": {
            "font_name": "宋体",
            "font_size": 10.5,
            "space_before": 0.0,
            "space_after": 2.3,
            "line_spacing": 10.5
        },
        "default_output_file": "code.docx",
        "template_file": "template.docx"
    }

# 加载配置
config = load_config()

# 从配置文件中读取常量
MAX_LINES = config['max_lines']
FIRST_PAGE_FILE_PATH = config['first_page_file_path']
DEFAULT_INDIRS = config['default_indirs']
DEFAULT_EXTS = config['default_exts']
DEFAULT_COMMENT_CHARS = tuple(config['default_comment_chars'])
DEFAULT_EXCLUDES = config.get('default_excludes', ['node_modules', '.git', 'dist'])


def del_slash(dirs):
    """
    删除文件夹最后一位的/

    Args:
        dirs: 文件夹列表
    Returns:
        删除之后的文件夹
    """
    no_slash_dirs = []
    for dir_ in dirs:
        if dir_[-1] == '/':
            no_slash_dirs.append(dir_[: -1])
        else:
            no_slash_dirs.append(dir_)
    return no_slash_dirs


class CodeFinder(object):
    """
    给定一个目录，和若干个后缀名，
    递归地遍历该目录，找到该目录下
    所有以这些后缀结束的文件
    """
    def __init__(self, exts=None):
        """
        Args:
            exts: 后缀名，默认为以py结尾
        """
        self.exts = exts if exts else ['py']

    def is_code(self, file):
        for ext in self.exts:
            if file.endswith(ext):
                return True
        return False

    @staticmethod
    def is_hidden_file(file):
        """
        是否是隐藏文件
        """
        return file[0] == '.'

    @staticmethod
    def should_be_excluded(file_path, excludes=None):
        """
        是否需要略过此文件或目录
        
        Args:
            file_path: 文件或目录的绝对路径
            excludes: 排除的路径列表
        Returns:
            bool: 是否应该被排除
        """
        if not excludes:
            return False
        if not isinstance(excludes, list):
            excludes = [excludes]
        
        # 检查路径中是否包含需要排除的目录名
        import os
        path_parts = file_path.split(os.sep)
        
        for exclude in excludes:
            # 检查绝对路径匹配
            if file_path.startswith(exclude):
                return True
            # 检查目录名匹配
            if exclude in path_parts:
                return True
            # 检查相对路径匹配
            if os.path.basename(file_path) == exclude:
                return True
                
        return False

    def find(self, indir, excludes=None, default_excludes=True):
        """
        给定一个文件夹查找这个文件夹下所有的代码

        Args:
            indir: 需要查到代码的目录
            excludes: 用户指定的排除文件或目录
            default_excludes: 是否使用默认排除目录
        Returns:
            代码文件列表
        """
        # 合并默认排除和用户指定排除
        all_excludes = []
        if default_excludes:
            all_excludes.extend(DEFAULT_EXCLUDES)
        if excludes:
            if isinstance(excludes, list):
                all_excludes.extend(excludes)
            else:
                all_excludes.append(excludes)
        
        files = []
        for entry in scandir(indir):
            # 防止根目录有一些含有非常多文件的隐藏文件夹
            # 例如，.git文件，如果不排除，此程序很难运行
            entry_name = entry.name
            if self.is_hidden_file(entry_name):
                continue
                
            entry_path = abspath(entry.path)
            
            # 检查是否应该排除此目录或文件
            if self.should_be_excluded(entry_path, all_excludes):
                continue
                
            if entry.is_file():
                if self.is_code(entry_name):
                    files.append(entry_path)
                continue
            
            # 递归处理子目录
            for file in self.find(entry_path, excludes=excludes, default_excludes=default_excludes):
                files.append(file)
                
        logger.debug('在%s目录下找到%d个代码文件.', indir, len(files))
        return files


class BaseCodeProcessor(object):
    """
    基础代码处理类，确保 DOCX 和 PDF 格式处理逻辑一致
    """
    def __init__(self, comment_chars=None):
        self.comment_chars = comment_chars if comment_chars else DEFAULT_COMMENT_CHARS
    
    @staticmethod
    def is_blank_line(line):
        """
        判断是否是空行
        """
        return not bool(line.strip())

    def is_comment_line(self, line):
        """
        判断是否是注释行
        """
        line = line.lstrip()  # 去除左侧缩进
        for comment_char in self.comment_chars:
            if line.startswith(comment_char):
                return True
        return False
    
    def should_skip_line(self, line):
        """
        判断是否应该跳过这一行（空行或注释行）
        """
        line = line.rstrip()
        return self.is_blank_line(line) or self.is_comment_line(line)


class CodeWriter(BaseCodeProcessor):
    def __init__(
            self, font_name=None,
            font_size=None, space_before=None,
            space_after=None, line_spacing=None,
            command_chars=None, document=None
    ):
        super().__init__(command_chars)
        
        # 从配置文件获取默认值
        font_settings = config['default_font_settings']
        self.font_name = font_name or font_settings['font_name']
        self.font_size = font_size or font_settings['font_size']
        self.space_before = space_before if space_before is not None else font_settings['space_before']
        self.space_after = space_after if space_after is not None else font_settings['space_after']
        self.line_spacing = line_spacing if line_spacing is not None else font_settings['line_spacing']
        
        # 修复模板文件加载逻辑
        if not document:
            template_file = config.get('template_file', 'template.docx')
            template_path = os.path.join(os.path.dirname(__file__), template_file)
            
            # 检查模板文件是否存在
            if os.path.exists(template_path):
                self.document = Document(template_path)
            else:
                # 如果模板文件不存在，创建一个新的空文档
                logger.warning(f"模板文件 {template_path} 不存在，创建新的空文档")
                self.document = Document()
        else:
            self.document = document

    def write_header(self, title):
        """
        写入页眉
        """
        paragraph = self.document.sections[0].header.paragraphs[0]
        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
        run = paragraph.add_run(title)
        run.font.name = self.font_name
        run.font.size = Pt(self.font_size)
        return self

    def write_file(self, file):
        """
        把单个文件添加到程序文档里面
        """
        lines_count = 0
        try:
            with codecs.open(file, encoding='utf-8', errors='ignore') as fp:
                for line in fp:
                    line = line.rstrip()
                    if self.should_skip_line(line):
                        continue
                    
                    paragraph = self.document.add_paragraph()
                    paragraph.paragraph_format.space_before = Pt(self.space_before)
                    paragraph.paragraph_format.space_after = Pt(self.space_after)
                    paragraph.paragraph_format.line_spacing = Pt(self.line_spacing)
                    run = paragraph.add_run(line)
                    run.font.name = self.font_name
                    run.font.size = Pt(self.font_size)
                    
                    lines_count += 1
        except Exception as e:
            logger.warning(f"无法读取文件 {file}: {e}")
            
        return lines_count

    def save(self, file):
        self.document.save(file)


# class CodeCounter(BaseCodeProcessor):
#     """
#     代码行数统计器，用于软著申请
#     统计有效代码行数（排除空行和注释行）
#     """
#     def __init__(self, comment_chars=None):
#         """
#         Args:
#             comment_chars: 注释字符，默认为 #、//
#         """
#         super().__init__(comment_chars)
#         self.total_lines = 0
#         self.code_lines = 0
#         self.comment_lines = 0
#         self.blank_lines = 0
#         self.file_stats = []

class PDFWriter(BaseCodeProcessor):
    """PDF 文档写入器"""
    def __init__(
            self, font_name=None, font_size=None, 
            space_before=None, space_after=None, line_spacing=None,
            line_height=None, page_size=None,
            margin_top=None, margin_bottom=None,
            margin_left=None, margin_right=None,
            comment_chars=None
    ):
        if not PDF_AVAILABLE:
            raise ImportError("reportlab 库未安装，无法使用 PDF 输出功能")
            
        super().__init__(comment_chars)
            
        # 使用与 CodeWriter 相同的配置源
        font_settings = config['default_font_settings']
        pdf_settings = config.get('pdf_settings', {})
        
        # 字体设置 - 优先使用 default_font_settings
        self.font_name = font_name or font_settings.get('font_name', 'Helvetica')
        self.font_size = font_size or font_settings.get('font_size', 10)
        
        # 间距设置 - 与 CodeWriter 保持一致
        self.space_before = space_before if space_before is not None else font_settings.get('space_before', 0.0)
        self.space_after = space_after if space_after is not None else font_settings.get('space_after', 2.3)
        self.line_spacing = line_spacing if line_spacing is not None else font_settings.get('line_spacing', 10.5)
        
        # 行高设置
        self.line_height = line_height or pdf_settings.get('line_height', self.line_spacing)
        
        # 页面设置
        page_size_name = page_size or pdf_settings.get('page_size', 'A4')
        self.page_size = A4 if page_size_name == 'A4' else letter
        
        self.margin_top = margin_top or pdf_settings.get('margin_top', 72)
        self.margin_bottom = margin_bottom or pdf_settings.get('margin_bottom', 72)
        self.margin_left = margin_left or pdf_settings.get('margin_left', 72)
        self.margin_right = margin_right or pdf_settings.get('margin_right', 72)
        
        # 为页眉预留空间
        self.header_height = 30
        self.margin_top += self.header_height
        
        self.story = []
        self.title = ""
        
        # 注册中文字体（如果可用）
        self._register_fonts()
    
    def _register_fonts(self):
        """
        注册系统字体
        """
        try:
            import platform
            system = platform.system()
            font_registered = False
            
            if system == "Darwin":  # macOS
                font_paths = [
                    "/System/Library/Fonts/STHeiti Light.ttc",
                    "/System/Library/Fonts/PingFang.ttc",
                    "/Library/Fonts/Arial Unicode MS.ttf"
                ]
            elif system == "Windows":
                font_paths = [
                    "C:/Windows/Fonts/simsun.ttc",
                    "C:/Windows/Fonts/simhei.ttf",
                    "C:/Windows/Fonts/msyh.ttc"
                ]
            else:  # Linux
                font_paths = [
                    "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
                    "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf"
                ]
                
            for font_path in font_paths:
                if os.path.exists(font_path):
                    try:
                        pdfmetrics.registerFont(TTFont('CustomFont', font_path))
                        self.font_name = 'CustomFont'
                        font_registered = True
                        break
                    except:
                        continue
                    
            if not font_registered:
                self.font_name = 'Helvetica'  # 回退到默认字体
                
        except Exception as e:
            logger.warning(f"字体注册失败，使用默认字体: {e}")
            self.font_name = 'Helvetica'
    
    def write_header(self, title):
        """
        设置文档标题
        """
        self.title = title
        return self
    
    def write_file(self, file):
        """
        把单个文件添加到 PDF 文档里面
        """
        lines_count = 0
        
        # 创建段落样式
        style = ParagraphStyle(
            'CodeStyle',
            fontName=self.font_name,
            fontSize=self.font_size,
            leading=self.line_height,
            alignment=TA_LEFT,
            leftIndent=0,
            rightIndent=0,
            spaceAfter=2
        )
        
        try:
            with codecs.open(file, encoding='utf-8', errors='ignore') as fp:
                for line in fp:
                    original_line = line.rstrip()
                    if self.should_skip_line(original_line):
                        continue
                    
                    # 计算缩进级别
                    stripped_line = original_line.lstrip()
                    indent_count = len(original_line) - len(stripped_line)

                    # 转义 HTML 特殊字符
                    escaped_line = original_line.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')

                    # 为每行创建带缩进的段落样式
                    line_style = ParagraphStyle(
                        f'CodeStyle_{indent_count}',
                        parent=style,
                        leftIndent=indent_count * 8  # 每个空格/制表符缩进8个点
                    )

                    # 创建段落并添加到故事中
                    para = Paragraph(escaped_line, line_style)
                    self.story.append(para)
                    
                    lines_count += 1
        except Exception as e:
            logger.warning(f"无法读取文件 {file}: {e}")
            
        return lines_count
    
    def _create_header_footer(self, canvas, doc):
        """创建页眉页脚"""
        if self.title:
            # 保存当前状态
            canvas.saveState()
            
            # 设置页眉
            canvas.setFont(self.font_name, self.font_size)
            width, height = self.page_size
            
            # 计算页眉位置
            header_y = height - self.margin_top + self.header_height - 10
            
            # 在页面顶部绘制页眉文字
            canvas.drawCentredString(
                width / 2, 
                header_y, 
                self.title
            )
            
            # 添加页眉分割线
            line_y = header_y - 8  # 在页眉文字下方8个点的位置
            line_start_x = self.margin_left
            line_end_x = width - self.margin_right
            
            # 设置线条样式
            canvas.setLineWidth(0.5)  # 设置线条宽度
            canvas.setStrokeColorRGB(0, 0, 0)  # 设置线条颜色为黑色
            
            # 绘制水平分割线
            canvas.line(line_start_x, line_y, line_end_x, line_y)
            
            # 恢复状态
            canvas.restoreState()
    
    def save(self, file):
        """保存 PDF 文档"""
        from reportlab.platypus import PageTemplate, Frame
        from reportlab.lib.pagesizes import A4
        from reportlab.platypus import BaseDocTemplate
        
        # 创建自定义文档模板
        doc = BaseDocTemplate(
            file,
            pagesize=self.page_size,
            topMargin=self.margin_top,
            bottomMargin=self.margin_bottom,
            leftMargin=self.margin_left,
            rightMargin=self.margin_right
        )
        
        # 创建页面框架
        frame = Frame(
            self.margin_left,
            self.margin_bottom,
            self.page_size[0] - self.margin_left - self.margin_right,
            self.page_size[1] - self.margin_top - self.margin_bottom,
            leftPadding=0,
            bottomPadding=0,
            rightPadding=0,
            topPadding=0
        )
        
        # 创建页面模板
        template = PageTemplate(
            id='normal',
            frames=[frame],
            onPage=self._create_header_footer
        )
        
        # 添加模板到文档
        doc.addPageTemplates([template])
        
        # 构建 PDF
        doc.build(self.story)




class CodeCounter(BaseCodeProcessor):
    """
    代码行数统计器，用于软著申请
    统计有效代码行数（排除空行和注释行）
    """
    def __init__(self, comment_chars=None):
        """
        Args:
            comment_chars: 注释字符，默认为 #、//
        """
        self.comment_chars = comment_chars if comment_chars else DEFAULT_COMMENT_CHARS
        self.total_lines = 0
        self.code_lines = 0
        self.comment_lines = 0
        self.blank_lines = 0
        self.file_stats = []

    def count_file(self, file_path):
        """
        统计单个文件的代码行数
        
        Args:
            file_path: 文件路径
        Returns:
            dict: 包含文件统计信息的字典
        """
        file_total = 0
        file_code = 0
        file_comment = 0
        file_blank = 0
        
        try:
            with codecs.open(file_path, encoding='utf-8', errors='ignore') as fp:
                for line in fp:
                    file_total += 1
                    line = line.rstrip()
                    
                    if self.is_blank_line(line):
                        file_blank += 1
                    elif self.is_comment_line(line):
                        file_comment += 1
                    else:
                        file_code += 1
        except Exception as e:
            logger.warning(f"无法读取文件 {file_path}: {e}")
            return None
        
        file_stat = {
            'file': file_path,
            'total_lines': file_total,
            'code_lines': file_code,
            'comment_lines': file_comment,
            'blank_lines': file_blank
        }
        
        # 更新总计
        self.total_lines += file_total
        self.code_lines += file_code
        self.comment_lines += file_comment
        self.blank_lines += file_blank
        self.file_stats.append(file_stat)
        
        return file_stat

    def get_summary(self):
        """
        获取统计摘要
        
        Returns:
            dict: 统计摘要信息
        """
        return {
            'total_files': len(self.file_stats),
            'total_lines': self.total_lines,
            'code_lines': self.code_lines,
            'comment_lines': self.comment_lines,
            'blank_lines': self.blank_lines,
            'code_percentage': round(self.code_lines / self.total_lines * 100, 2) if self.total_lines > 0 else 0
        }

    def print_report(self, detailed=False):
        """
        打印统计报告
        
        Args:
            detailed: 是否显示详细信息（每个文件的统计）
        """
        summary = self.get_summary()
        
        print("\n" + "="*60)
        print("代码行数统计报告（软著申请用）")
        print("="*60)
        print(f"总文件数: {summary['total_files']}")
        print(f"总行数: {summary['total_lines']}")
        print(f"有效代码行数: {summary['code_lines']}")
        print(f"注释行数: {summary['comment_lines']}")
        print(f"空行数: {summary['blank_lines']}")
        print(f"代码行占比: {summary['code_percentage']}%")
        print("="*60)
        
        if detailed and self.file_stats:
            print("\n详细文件统计:")
            print("-"*80)
            print(f"{'文件路径':<50} {'总行数':<8} {'代码行':<8} {'注释行':<8} {'空行':<8}")
            print("-"*80)
            
            for stat in self.file_stats:
                filename = os.path.basename(stat['file'])
                if len(filename) > 47:
                    filename = "..." + filename[-44:]
                print(f"{filename:<50} {stat['total_lines']:<8} {stat['code_lines']:<8} {stat['comment_lines']:<8} {stat['blank_lines']:<8}")
            print("-"*80)

    def save_report(self, output_file):
        """
        保存统计报告到文件
        
        Args:
            output_file: 输出文件路径
        """
        summary = self.get_summary()
        
        with open(output_file, 'w', encoding='utf-8') as f:
            f.write("代码行数统计报告（软著申请用）\n")
            f.write("="*60 + "\n")
            f.write(f"统计时间: {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
            f.write(f"总文件数: {summary['total_files']}\n")
            f.write(f"总行数: {summary['total_lines']}\n")
            f.write(f"有效代码行数: {summary['code_lines']}\n")
            f.write(f"注释行数: {summary['comment_lines']}\n")
            f.write(f"空行数: {summary['blank_lines']}\n")
            f.write(f"代码行占比: {summary['code_percentage']}%\n")
            f.write("="*60 + "\n\n")
            
            f.write("详细文件统计:\n")
            f.write("-"*80 + "\n")
            f.write(f"{'文件路径':<50} {'总行数':<8} {'代码行':<8} {'注释行':<8} {'空行':<8}\n")
            f.write("-"*80 + "\n")
            
            for stat in self.file_stats:
                f.write(f"{stat['file']:<50} {stat['total_lines']:<8} {stat['code_lines']:<8} {stat['comment_lines']:<8} {stat['blank_lines']:<8}\n")
            f.write("-"*80 + "\n")
        
        print(f"统计报告已保存到: {output_file}")


@click.command(name='pyerz')
@click.option(
    '-t', '--title', default=config['default_title'],
    help=f"软件名称+版本号，默认为{config['default_title']}，此名称用于生成页眉"
)
@click.option(
    '-i', '--indir', 'indirs',
    multiple=True, type=click.Path(exists=True),
    help='源码所在文件夹，可以指定多个，默认为当前目录'
)
@click.option(
    '-e', '--ext', 'exts',
    multiple=True, help='源代码后缀，可以指定多个，默认为Python源代码'
)
@click.option(
    '-c', '--comment-char', 'comment_chars',
    multiple=True, help='注释字符串，可以指定多个，默认为#、//'
)
@click.option(
    '--font-name', default=config['default_font_settings']['font_name'],
    help=f"字体，默认为{config['default_font_settings']['font_name']}"
)
@click.option(
    '--font-size', default=config['default_font_settings']['font_size'],
    type=click.FloatRange(min=1.0),
    help=f"字号，默认为{config['default_font_settings']['font_size']}号"
)
@click.option(
    '--space-before', default=config['default_font_settings']['space_before'],
    type=click.FloatRange(min=0.0),
    help=f"段前间距，默认为{config['default_font_settings']['space_before']}"
)
@click.option(
    '--space-after', default=config['default_font_settings']['space_after'],
    type=click.FloatRange(min=0.0),
    help=f"段后间距，默认为{config['default_font_settings']['space_after']}"
)
@click.option(
    '--line-spacing', default=config['default_font_settings']['line_spacing'],
    type=click.FloatRange(min=0.0),
    help=f"行距，默认为固定值{config['default_font_settings']['line_spacing']}"
)
@click.option(
    '--exclude', 'excludes',
    multiple=True, type=click.Path(),
    help='需要排除的文件或路径，可以指定多个（会自动排除常见目录如node_modules、.git、dist等）'
)
@click.option(
    '--no-default-excludes', is_flag=True,
    help='不使用默认排除目录，只使用用户指定的排除项'
)
@click.option(
    '-o', '--outfile', default=config['default_output_file'],
    type=click.Path(exists=False),
    help=f"输出文件，默认为当前目录的{config['default_output_file']}"
)
@click.option(
    '--format', 'output_format', 
    type=click.Choice(['docx', 'pdf'], case_sensitive=False),
    default='docx',
    help='输出格式，支持 docx 和 pdf，默认为 docx'
)
@click.option('-v', '--verbose', is_flag=True, help='打印调试信息')
def main(
        title, indirs, exts,
        comment_chars, font_name,
        font_size, space_before,
        space_after, line_spacing,
        excludes, no_default_excludes, 
        outfile, output_format, verbose
):
    print('start...')
    lines_written = 0
    if not indirs:
        indirs = DEFAULT_INDIRS
    if not exts:
        exts = DEFAULT_EXTS
    if not comment_chars:
        comment_chars = DEFAULT_COMMENT_CHARS
    if verbose:
        logging.basicConfig(level=logging.DEBUG)

    # 根据输出格式调整默认文件名
    if outfile == config['default_output_file'] and output_format.lower() == 'pdf':
        outfile = config.get('default_pdf_output_file', 'code.pdf')
    else:
        # 确保输出文件有正确的后缀
        import os
        file_name, file_ext = os.path.splitext(outfile)
        if output_format.lower() == 'pdf':
            if file_ext.lower() != '.pdf':
                outfile = file_name + '.pdf'
        else:  # docx格式
            if file_ext.lower() != '.docx':
                outfile = file_name + '.docx'

    # 第零步，把所有的路径都转换为绝对路径
    indirs = [abspath(indir) for indir in indirs]
    excludes = del_slash(
        [abspath(exclude) for exclude in excludes] if excludes else []
    )

    # 第一步，查找代码文件
    finder = CodeFinder(exts)
    files = []
    for indir in indirs:
        found_files = finder.find(
            indir, 
            excludes=excludes, 
            default_excludes=not no_default_excludes
        )
        files.extend(found_files)
    
    # 调整文件顺序，把首页放在前面
    if FIRST_PAGE_FILE_PATH in files:
        files.remove(FIRST_PAGE_FILE_PATH)
    files.insert(0, FIRST_PAGE_FILE_PATH)
    
    # 第二步，根据输出格式选择相应的写入器
    if output_format.lower() == 'pdf':
        if not PDF_AVAILABLE:
            print("错误: PDF 输出功能不可用，请安装 reportlab 库: pip install reportlab")
            return 1
        
        writer = PDFWriter(
            comment_chars=comment_chars,
            font_name=font_name,
            font_size=font_size,
            space_before=space_before,
            space_after=space_after,
            line_spacing=line_spacing
        )
    else:
        writer = CodeWriter(
            command_chars=comment_chars,
            font_name=font_name,
            font_size=font_size,
            space_before=space_before,
            space_after=space_after,
            line_spacing=line_spacing
        )
    
    writer.write_header(title)
    
    for file in files:
        lines_written = lines_written + writer.write_file(file)
        if lines_written > MAX_LINES:
            print('total lines:{}'.format(lines_written))
            break
    
    writer.save(outfile)
    print(f'文档已保存为: {outfile} (格式: {output_format.upper()})')
    return 0

@click.command(name='count-lines')
@click.option(
    '-i', '--indir', 'indirs',
    multiple=True, type=click.Path(exists=True),
    help='源码所在文件夹，可以指定多个，默认为当前目录'
)
@click.option(
    '-e', '--ext', 'exts',
    multiple=True, help='源代码后缀，可以指定多个，默认为py,cc,cpp,h,js'
)
@click.option(
    '-c', '--comment-char', 'comment_chars',
    multiple=True, help='注释字符串，可以指定多个，默认为#、//'
)
@click.option(
    '--exclude', 'excludes',
    multiple=True, type=click.Path(),
    help='需要排除的文件或路径，可以指定多个（会自动排除常见目录如node_modules、.git、dist等）'
)
@click.option(
    '--no-default-excludes', is_flag=True,
    help='不使用默认排除目录，只使用用户指定的排除项'
)
@click.option(
    '-o', '--output', 'output_file',
    type=click.Path(),
    help='输出报告文件路径（可选）'
)
@click.option(
    '-d', '--detailed', is_flag=True,
    help='显示详细的文件统计信息'
)
@click.option('-v', '--verbose', is_flag=True, help='打印调试信息')
def count_lines(
        indirs, exts, comment_chars,
        excludes, no_default_excludes, output_file, detailed, verbose
):
    """
    统计指定目录下的代码行数，用于软著申请
    """
    print('开始统计代码行数...')
    
    if not indirs:
        indirs = DEFAULT_INDIRS
    if not exts:
        exts = DEFAULT_EXTS
    if not comment_chars:
        comment_chars = DEFAULT_COMMENT_CHARS
    if verbose:
        logging.basicConfig(level=logging.DEBUG)

    # 转换为绝对路径
    indirs = [abspath(indir) for indir in indirs]
    excludes = del_slash(
        [abspath(exclude) for exclude in excludes] if excludes else []
    )

    # 查找代码文件
    finder = CodeFinder(exts)
    files = []
    for indir in indirs:
        found_files = finder.find(
            indir, 
            excludes=excludes, 
            default_excludes=not no_default_excludes
        )
        files.extend(found_files)
    
    if not files:
        print("未找到任何代码文件")
        return 1
    
    print(f"找到 {len(files)} 个代码文件，开始统计...")
    
    # 显示排除的目录信息
    if not no_default_excludes:
        print(f"默认排除目录: {', '.join(DEFAULT_EXCLUDES)}")
    if excludes:
        print(f"用户指定排除: {', '.join(excludes)}")
    
    # 统计代码行数
    counter = CodeCounter(comment_chars)
    
    for file_path in files:
        if verbose:
            print(f"正在处理: {file_path}")
        counter.count_file(file_path)
    
    # 显示报告
    counter.print_report(detailed=detailed)
    
    # 保存报告到文件
    if output_file:
        counter.save_report(output_file)
    
    return 0


# 创建命令组
@click.group()
def cli():
    """Python代码转docx工具集"""
    pass

# 添加命令到组
cli.add_command(main, name='to-docx')
cli.add_command(count_lines, name='count')

# 在文件末尾添加新的命令
@click.command(name='markdown-to-pdf')
@click.option(
    '-i', '--input', 'input_file',
    type=click.Path(exists=True),
    required=True,
    help='输入的markdown文件路径'
)
@click.option(
    '-o', '--output', 'output_file',
    type=click.Path(),
    required=True,
    help='输出的PDF文件路径'
)
@click.option(
    '-t', '--title',
    help='PDF文档标题'
)
@click.option(
    '--font-name',
    default='Helvetica',
    help='字体名称，默认为Helvetica'
)
@click.option(
    '--font-size',
    type=click.FloatRange(min=8.0, max=72.0),
    default=12.0,
    help='字体大小，默认为12'
)
@click.option('-v', '--verbose', is_flag=True, help='打印调试信息')
def markdown_to_pdf_command(input_file, output_file, title, font_name, font_size, verbose):
    """将Markdown文件转换为PDF"""
    if verbose:
        logging.basicConfig(level=logging.DEBUG)
    
    if not MARKDOWN_PDF_AVAILABLE:
        print("错误: markdown转PDF功能不可用，请安装相关依赖:")
        print("pip install markdown Pillow")
        return 1
    
    try:
        success = markdown_to_pdf(
            input_file,
            output_file,
            title=title,
            font_name=font_name,
            font_size=font_size
        )
        
        if success:
            print(f"成功生成PDF: {output_file}")
            return 0
        else:
            print("PDF生成失败")
            return 1
            
    except Exception as e:
        print(f"转换过程中出错: {e}")
        return 1

cli.add_command(main, name='to-docx')
cli.add_command(count_lines, name='count')
cli.add_command(markdown_to_pdf_command, name='md-to-pdf')

if __name__ == '__main__':
    cli()
